%{
/* Parser for configuration file specification of Milestone 1 - ECE297. */
#include <string.h>
#include <stdio.h>
#include <stdbool.h> /* for true */
#include "utils.h"
#include "storage.h" 
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "database.h"

int numCols, numTables; 
bool doneTable;
char colNames[MAX_COLUMNS_PER_TABLE][MAX_COLNAME_LEN+1];
int colValues[MAX_COLUMNS_PER_TABLE];
int tableNames[MAX_TABLES][MAX_TABLE_LEN+1];
char tableParameterForQuery[1050];
char tempColName[MAX_COLNAME_LEN+2]; /* add 2 to detect if more than max_colname_len*/
int k; 
/* strcpy(colNames[0], "blah"); USAGE */

struct table *tl, *t;
struct configuration *c;

/* define a linked list of table names */
struct table
{
  char *table_name;
  struct table *next;
};

struct table *table_list; /* first element in table name list */  

/* char *trimwhitespace(char *str) in utils.c*/

%}

%union
{
  char *sval; /* value of the string */
  int  pval; /* value of the port */
}


%token <sval> IMPLICIT_KEY_WITH_COLON 
%token <sval>  CHARACTER_WITH_BRACKET
%token <sval> STRING
%token <sval> LENGTH
%token <pval> PORT_NUMBER CONCURRENCY_NUMBER
%token HOST_PROPERTY PORT_PROPERTY DDIR_PROPERTY TABLE USERNAME_PROPERTY PASSWORD_PROPERTY CONCURRENCY_PROPERTY
%token WHITE_SPACE IMPLICIT_KEY_WITH_COLON LENGTH COMMA INTEGER CHARACTER_WITH_BRACKET NEWLINE ENDOFFILE

%%

/* When any config param error occurs, just return -1, server will exit failure nicely*/

property_list: /* do nothing */
   | property_list exp 
   | property_list 
   ;

exp: eval
   |
   exp eval
   ;

eval: 
   HOST_PROPERTY STRING NEWLINE
   {
printf("HOST_PROPERTY STRING NEWLINE\n");
	initialize_configuration();
	if (c->hostDone == true) 
	{
	    printf("Error: Host already given\n");
	    return -1;
	}
	c->host = strdup($2);
	/* Check length */
	if (strlen(c->host) > MAX_HOST_LEN)
	{
	    printf("Error: Host exceeds MAX_HOST_LEN\n");
	    return -1;
	}
	/* Check that it is indeed a server IP Address */ 
	if (strcmp(c->host,"localhost") != 0) //
        {
	    // Check if IP address satisfy constraint
	    //inet_pton() returns 1 on success.
	    //It returns -1 if there was an error (errno is set), or 0 if the input isn't a valid IP address.
	    struct sockaddr_in saTemp;
	    // store this IP address in sa:
	    int IPCheck = inet_pton(AF_INET, c->host, &(saTemp.sin_addr)); // for IPv4
		// returns 1 on success, -1 if there was an error, 0 if input isn't valid
	    if (IPCheck == 0)
	    {
	    	printf("Error: %s is not a valid IP Address\n", c->host);
	    	sprintf(message, "Error: %s is not a valid IP Address\n", c->host);
	    	printf("%s", message);
	    	logger(fileClient, message);
	    	return -1;
	    }
	}
	// else it is a localhost so that means it is a server port
	c->hostDone = true;
   }

   | ENDOFFILE

   {
	printf("ENDOFFILE\n");
	return 0; /* signal to utils.c no errors */ 
   }

   | eval ENDOFFILE

   {
	printf("eval ENDOFFILE\n");
	return 0; /* signal to utils.c no errors */ 
   }

   | 
    CONCURRENCY_PROPERTY CONCURRENCY_NUMBER NEWLINE
    {
	printf("CONCURRENCY_PROPERTY CONCURRENCY_NUMBER NEWLINE\n");
	initialize_configuration();
	if (c->concurrencyDone == true) 
	{
	    printf("Error: Concurrency number already given\n");
	    return -1;
	}
	c->concurrency = $2;
	/* Update Configurations  */
	c->concurrencyDone = true;
    }

   | 
    eval CONCURRENCY_PROPERTY CONCURRENCY_NUMBER NEWLINE
    {
	printf("eval CONCURRENCY_PROPERTY CONCURRENCY_NUMBER NEWLINE\n");
	initialize_configuration();
	if (c->concurrencyDone == true) 
	{
	    printf("Error: Concurrency number already given\n");
	    return -1;
	}
	c->concurrency = $3;
	/* Update Configurations  */
	c->concurrencyDone = true;
    }
	
   |

   USERNAME_PROPERTY STRING NEWLINE
   {
printf("USERNAME_PROPERTY STRING NEWLINE\n");
	initialize_configuration();
	if (c->usernameDone == true) 
	{
	    printf("Error: Username already given\n");
	    return -1;
	}
	c->username = strdup($2);
	if (strlen(c->username) > MAX_USERNAME_LEN)
	{
	    printf("Error: Username exceeds MAX_USERNAME_LEN\n");
	    return -1;
	}
	c->usernameDone = true;
   }

   |

   PASSWORD_PROPERTY STRING NEWLINE
   {
printf("PASSWORD_PROPERTY STRING NEWLINE\n");
	initialize_configuration();
	if (c->passwordDone == true) 
	{
	    printf("Error: Password already given\n");
	    return -1;
	}
	c->password = strdup($2);
	if (strlen(c->password) > MAX_ENC_PASSWORD_LEN)
	{
	    printf("Error: Encrypted password exceeds c\n");
	    return -1;
	}
	c->passwordDone = true; 
   }

   |  

   PORT_PROPERTY PORT_NUMBER NEWLINE
   {
printf("PORT_PROPERTY PORT_NUMBER NEWLINE\n");
	initialize_configuration();
	if (c->portDone == true) 
	{
	    printf("Error: Port already given\n");
	    return -1;
	}
	c->port = $2;
	/* Check length */
    	int count = numDigits(c->port); // defined in utils.h
    	if (count > MAX_PORT_LEN)
    	{
       	    printf("Error: port %d exceeds maximum length of %d\n", c->port, MAX_PORT_LEN);
       	    sprintf(message, "Error: port %d exceeds maximum length of %d\n", c->port, MAX_PORT_LEN);
            printf("%s", message);
            logger(fileClient, message);
	    return -1;
  	}
	/* Check value of port to be an IP Address */
    	// Check if port satisfy constraint (d), 0 <= d <= 65535
   	if( (c->port > 65535) || (c->port < 0))
   	{
	    printf("Error: %d is not a valid port number\n", c->port);
	    sprintf(message, "Error: %d is not a valid port number\n", c->port);
	    printf("%s", message);
	    logger(fileClient, message);
	    return -1;
	}
	c->portDone = true;
   }

   |

   table_list term next_list
   {
	printf("table_list term next_list\n");
	c->tableDone = true;
   }
 
   |
   table_list term
   {
	printf("table_list term\n");
	c->tableDone = true;
   }

   |

   DDIR_PROPERTY STRING NEWLINE
   {
printf("DDIR_PROPERTY STRING NEWLINE\n");
	initialize_configuration();
	c->data_dir = strdup ($2);
	if (strlen(c->data_dir) > MAX_PATH_LEN)
	{
	    printf("Error: Path exceeds MAX_PATH_LEN\n");
	    return -1;
	}
   }

   |

   eval HOST_PROPERTY STRING NEWLINE
   {
printf("eval HOST_PROPERTY STRING NEWLINE\n");
	initialize_configuration();
	if (c->hostDone == true) 
	{
	    printf("Error: Host already given\n");
	    return -1;
	}
	c->host = strdup($3);
	/* Check length */
	if (strlen(c->host) > MAX_HOST_LEN)
	{
	    printf("Error: Host exceeds MAX_HOST_LEN\n");
	    return -1;
	}
	/* Check that it is indeed a server IP Address */ 
	if (strcmp(c->host,"localhost") != 0) //
        {
	    // Check if IP address satisfy constraint
	    //inet_pton() returns 1 on success.
	    //It returns -1 if there was an error (errno is set), or 0 if the input isn't a valid IP address.
	    struct sockaddr_in saTemp;
	    // store this IP address in sa:
	    int IPCheck = inet_pton(AF_INET, c->host, &(saTemp.sin_addr)); // for IPv4
		// returns 1 on success, -1 if there was an error, 0 if input isn't valid
	    if (IPCheck == 0)
	    {
	    	printf("Error: %s is not a valid IP Address\n", c->host);
	    	sprintf(message, "Error: %s is not a valid IP Address\n", c->host);
	    	printf("%s", message);
	    	logger(fileClient, message);
	    	return -1;
	    }
	}
	// else it is a localhost so that means it is a server port
	c->hostDone = true;
   }

   |

   eval USERNAME_PROPERTY STRING NEWLINE
   {

printf("eval USERNAME_PROPERTY STRING NEWLINE\n");
	initialize_configuration();
	if (c->usernameDone == true) 
	{
	    printf("Error: Username already given\n");
	    return -1;
	}
	c->username = strdup($3);
	if (strlen(c->username) > MAX_USERNAME_LEN)
	{
	    printf("Error: Username exceeds MAX_USERNAME_LEN\n");
	    return -1;
	}
	c->usernameDone = true;
   }

   |

   eval PASSWORD_PROPERTY STRING NEWLINE
   {
printf("eval PASSWORD_PROPERTY STRING NEWLINE\n");
	initialize_configuration();
	if (c->passwordDone == true) 
	{
	    printf("Error: Password already given\n");
	    return -1;
	}
	c->password = strdup($3);
	if (strlen(c->password) > MAX_ENC_PASSWORD_LEN)
	{
	    printf("Error: Encrypted password exceeds c\n");
	    return -1;
	}
	c->passwordDone = true;
   }

   |

   eval PORT_PROPERTY PORT_NUMBER NEWLINE
   {
	printf("eval PORT_PROPERTY PORT_NUMBER\n");
	initialize_configuration();
	if (c->portDone == true) 
	{
	    printf("Error: Port already given\n");
	    return -1;
	}
	c->port = $3;
	/* Check length */
    	int count = numDigits(c->port); // defined in utils.h
    	if (count > MAX_PORT_LEN)
    	{
       	    printf("Error: port %d exceeds maximum length of %d\n", c->port, MAX_PORT_LEN);
       	    sprintf(message, "Error: port %d exceeds maximum length of %d\n", c->port, MAX_PORT_LEN);
            printf("%s", message);
            logger(fileClient, message);
	    return -1;
  	}
	/* Check value of port to be an IP Address */
    	// Check if port satisfy constraint (d), 0 <= d <= 65535
   	if( (c->port > 65535) || (c->port < 0))
   	{
	    printf("Error: %d is not a valid port number\n", c->port);
	    sprintf(message, "Error: %d is not a valid port number\n", c->port);
	    printf("%s", message);
	    logger(fileClient, message);
	    return -1;
	}
	c->portDone = true;
   }

   |

   eval table_list term next_list 
   {
	printf("eval table_list term next_list\n");
	/* Here means done 1 table with multiple records  */
	
	/* Insert into query */
	/* TODO TODO TODO TODO TODO */
	if(insertTable(tableNames[numTables]) == 0) // insert the new table
	{
	    printf("Error: insertTable not successful\n");
	    return -1;
	}
printf("BEFORE INSERTVALUE\n\n\n\n");
printf("%s\n", tableParameterForQuery);
	 k = insertValue(tableNames[numTables],"InitialKey",tableParameterForQuery, 0);
printf("K(1 means inserted 2 means updated) is %d\n", k);
printf("%s\n", tableNames[numTables]);
printf("%s\n", tableParameterForQuery);
	/* Initialize tableParameterForQuery*/
	strcpy(tableParameterForQuery, "");
	doneTable = true;
	/*Finally increment number of tables */
	numTables++;
	c->tableDone = true;
   }
	
   |

   eval table_list term
   {
	printf("eval table_list term \n");
	/* Here means done 1 table and only have 1 record*/

	/* Insert into query */
	/* TODO TODO TODO TODO TODO */
	if(insertTable(tableNames[numTables]) == 0) // insert the new table
	{
	    printf("Error: insertTable not successful\n");
	    return -1;
	}
printf("BEFORE INSERTVALUE\n\n\n\n");
printf("%s\n", tableParameterForQuery);
	k = insertValue(tableNames[numTables],"InitialKey",tableParameterForQuery, 0 );
printf("K is %d\n", k);
printf("%s\n", tableNames[numTables]);

	/* Initialize tableParameterForQuery*/
	strcpy(tableParameterForQuery, "");
	doneTable = true;
	/*Finally increment number of tables */
	numTables++;
	c->tableDone = true;
   }

   |

   eval DDIR_PROPERTY STRING NEWLINE
   {
	printf("eval DDIR_PROPERTY STRING\n");
	initialize_configuration();
	c->data_dir = strdup ($3);
	if (strlen(c->data_dir) > MAX_PATH_LEN)
	{
	    printf("Error: Path exceeds MAX_PATH_LEN\n");
	    return -1;
	}
   }

   | eval NEWLINE
   {
	printf("eval NEWLINE\n");

   }

   |	
      NEWLINE
   {
	printf("NEWLINE\n");
    }
   ;

table_list: 

    table_list TABLE STRING IMPLICIT_KEY_WITH_COLON CHARACTER_WITH_BRACKET LENGTH 
    { 										/* Not short if need this lane NEWLINE */
	printf("table_list TABLE STRING IMPLICIT_KEY_WITH_COLON CHARACTER_WITH_BRACKET LENGTH\n");
printf("11111111 NEVER HERE TREAT AS 2\n");
	initialize_configuration();
	/* Initialize number of columns, column names and column values */
	 clearColumnNames();
	/* Check table name length */
 	if (strlen($3) > MAX_TABLE_LEN)
	{
	    printf("Table length too long\n");
	    return -1;
	}
	/* Get table name */
	strcpy(tableNames[numTables],$3);
	/* Check if table exists */
	if (!checkTableExist(tableNames[numTables], numTables))
	{
	    printf("Duplicate table\n");
	    return -1;
	}
	/* Get first key */
	strcpy(tempColName, $4);
	tempColName[strlen(tempColName)-2] = '\0';
	/* Check column name length */	
	if (strlen(tempColName) > MAX_COLNAME_LEN)
	{
	    printf("Column name too long\n");
	    return -1;
	}
	/* Store column name */
	strcpy(colNames[numCols], tempColName);
	/* Check column exist */
	if (!checkColumnExist(colNames[numCols], numCols))
	{
	    printf("Duplicate Columns\n");
	    return -1;
	}
	/* Get length */
	strcpy(tempColName, $6);
	tempColName[strlen(tempColName)-1] = '\0';
	colValues[numCols] = atoi(tempColName);
	/* Check length of maxstrtpe_size */
	if (colValues[numCols] > MAX_STRTYPE_SIZE)
	{
	    printf("MAx strtype size exceeded\n");
	    return -1;
	}
	/* Append query table insert */
	sprintf(message, "%s c%d",colNames[numCols], colValues[numCols]);
	strcat(tableParameterForQuery,message);
	/* Finally, increment number of columns */	
	numCols++;
	/* Check number of columns */
	if (numCols > MAX_COLUMNS_PER_TABLE)
	{
	    printf("Too many columns in 1 table\n");
	    return -1; 
	}
printf("QUERYNAMEis:%s\n", tableParameterForQuery);
printf("%s\n", tableNames[numTables]);
printf("%s\n", tempColName);
    }

    | TABLE STRING IMPLICIT_KEY_WITH_COLON CHARACTER_WITH_BRACKET LENGTH

    {
	printf("TABLE STRING IMPLICIT_KEY_WITH_COLON CHARACTER_WITH_BRACKET LENGTH\n");
		/*   printf("KEY is %s, character is %s\n", $3, $5) */
printf("22222222\n");
	initialize_configuration();
	/* Initialize number of columns */
	 clearColumnNames();

	/* Check table name length */
 	if (strlen($2) > MAX_TABLE_LEN)
	{
	    printf("Table length too long\n");
	    return -1;
	}
	/* Get table name */
	strcpy(tableNames[numTables],$2 );
	/* Check if table exists */
	if (!checkTableExist(tableNames[numTables], numTables))
	{
	    printf("Duplicate table\n");
	    return -1;
	}
	/* Get first column */
	strcpy(tempColName, $3);
	tempColName[strlen(tempColName)-2] = '\0';
	/* Check column name length */	
	if (strlen(tempColName) > MAX_COLNAME_LEN)
	{
	    printf("Column name too long\n");
	    return -1;
	}
	/* Store column name */
	strcpy(colNames[numCols], tempColName);
	/* Check column exist */
	if (!checkColumnExist(colNames[numCols], numCols))
	{
	    printf("Duplicate Columns\n");
	    return -1;
	}

	/* Get length */
	strcpy(tempColName, $5);
	tempColName[strlen(tempColName)-1] = '\0';
	colValues[numCols] = atoi(tempColName);
	/* Check length of maxstrtpe_size */
	if (colValues[numCols] > MAX_STRTYPE_SIZE)
	{
	    printf("MAx strtype size exceeded\n");
	    return -1;
	}
	/* Append query table insert */
	sprintf(message, "%s c%d",colNames[numCols], colValues[numCols]);
	strcat(tableParameterForQuery,message);
	/* Finally, increment number of columns */	
	numCols++;
	/* Check number of columns */
	if (numCols > MAX_COLUMNS_PER_TABLE)
	{
	    printf("Too many columns in 1 table\n");
	    return -1; 
	}
 
printf("QUERYNAMEis:%s\n", tableParameterForQuery);
printf("LENGTH:%d\n",	colValues[numCols]);
printf("%s\n", tableNames[numTables]);
printf("%s\n", tempColName);
    }

    | TABLE STRING IMPLICIT_KEY_WITH_COLON INTEGER

    {
	printf("TABLE STRING IMPLICIT_KEY_WITH_COLON INTEGER\n");
printf("33333333\n");
	initialize_configuration();
	/* Initialize number of columns */
	 clearColumnNames();
	/* Check table name length */
 	if (strlen($2) > MAX_TABLE_LEN)
	{
	    printf("Table length too long\n");
	    return -1;
	}
	/* Get table name */
	strcpy(tableNames[numTables],$2 );
	/* Check if table exists */
	if (!checkTableExist(tableNames[numTables], numTables))
	{
	    printf("Duplicate table\n");
	    return -1;
	}
	/* Get first key */
	strcpy(tempColName, $3);
	tempColName[strlen(tempColName)-2] = '\0';
	/* Check column name length */	
	if (strlen(tempColName) > MAX_COLNAME_LEN)
	{
	    printf("Column name too long\n");
	    return -1;
	}
	/* Store column name */
	strcpy(colNames[numCols], tempColName);
	/* Check column exist */
	if (!checkColumnExist(colNames[numCols], numCols))
	{
	    printf("Duplicate Columns\n");
	    return -1;
	}
	/* Append query table insert */
	sprintf(message, "%s i",colNames[numCols]);
	strcat(tableParameterForQuery,message);
	/* Finally, increment number of columns */	
	numCols++;
	/* Check number of columns */
	if (numCols > MAX_COLUMNS_PER_TABLE)
	{
	    printf("Too many columns in 1 table\n");
	    return -1; 
	}
printf("QUERYNAMEis:%s\n", tableParameterForQuery);
printf("%s\n", tableNames[numTables]);
printf("%s\n", tempColName);
    }

    | table_list TABLE STRING IMPLICIT_KEY_WITH_COLON INTEGER

    {
printf("44444444 NEVER HERE TREAT AS 2 \n");
	printf("table_list TABLE STRING IMPLICIT_KEY_WITH_COLON INTEGER\n");
	/* Initialize number of columns */
	initialize_configuration();
	clearColumnNames();
	/* Check table name length */
 	if (strlen($3) > MAX_TABLE_LEN)
	{
	    printf("Table length too long\n");
	    return -1;
	}
	/* Get table name */
	strcpy(tableNames[numTables],$3 );
	/* Check if table exists */
	if (!checkTableExist(tableNames[numTables], numTables))
	{
	    printf("Duplicate table\n");
	    return -1;
	}
	/* Get first key */
	strcpy(tempColName, $4);
	tempColName[strlen(tempColName)-2] = '\0';
	/* Check column name length */	
	if (strlen(tempColName) > MAX_COLNAME_LEN)
	{
	    printf("Column name too long\n");
	    return -1;
	}
	/* Store column name */
	strcpy(colNames[numCols], tempColName);
	/* Check column exist */
	if (!checkColumnExist(colNames[numCols], numCols))
	{
	    printf("Duplicate Columns\n");
	    return -1;
	}
	/* Append query table insert */
	sprintf(message, "%s i",colNames[numCols]);
	strcat(tableParameterForQuery,message);
	/* Finally, increment number of columns */	
	numCols++;
	/* Check number of columns */
	if (numCols > MAX_COLUMNS_PER_TABLE)
	{
	    printf("Too many columns in 1 table\n");
	    return -1; 
	}
printf("QUERYNAMEis:%s\n", tableParameterForQuery);
printf("%s\n", tableNames[numTables]);
printf("%s\n", tempColName);
    }    
   ;

next_list:
	next_list IMPLICIT_KEY_WITH_COLON CHARACTER_WITH_BRACKET LENGTH term
	{
	   printf("next_list IMPLICIT_KEY_WITH_COLON CHARACTER_WITH_BRACKET LENGTH\n");
	   /*printf("KEY is %s, character is %s\n", $2, $3); */
printf("55555555\n");
	/* Get next column */
	strcpy(tempColName, $2);
	tempColName[strlen(tempColName)-2] = '\0';
	/* Check column name length */	
	if (strlen(tempColName) > MAX_COLNAME_LEN)
	{
	    printf("Column name too long\n");
	    return -1;
	}

	/* Store column name */
	strcpy(colNames[numCols], tempColName);
	/* Check column exist */
	if (!checkColumnExist(colNames[numCols], numCols))
	{
	    printf("Duplicate Columns\n");
	    return -1;
	}

	/* Get length */
	strcpy(tempColName, $4);
	tempColName[strlen(tempColName)-1] = '\0';
	colValues[numCols] = atoi(tempColName);
	/* Check length of maxstrtpe_size */
	if (colValues[numCols] > MAX_STRTYPE_SIZE)
	{
	    printf("MAx strtype size exceeded\n");
	    return -1;
	}
	/* Append query table insert */
	sprintf(message, "@%s c%d",colNames[numCols], colValues[numCols]);
	strcat(tableParameterForQuery,message);
	/* Finally, increment number of columns */	
	numCols++;
	/* Check number of columns */
	if (numCols > MAX_COLUMNS_PER_TABLE)
	{
	    printf("Too many columns in 1 table\n");
	    return -1; 
	}
printf("QUERYNAMEis:%s\n", tableParameterForQuery);
	}

	|

	IMPLICIT_KEY_WITH_COLON CHARACTER_WITH_BRACKET LENGTH term
	{
	  printf("IMPLICIT_KEY_WITH_COLON CHARACTER_WITH_BRACKET LENGTH\n");
printf("6666666 NEVER HERE TREAT AS 5\n");
	/* Get next column */
	strcpy(tempColName, $1);
	tempColName[strlen(tempColName)-2] = '\0';
	/* Check column name length */	
	if (strlen(tempColName) > MAX_COLNAME_LEN)
	{
	    printf("Column name too long\n");
	    return -1;
	}

	/* Store column name */
	strcpy(colNames[numCols], tempColName);
	/* Check column exist */
	if (!checkColumnExist(colNames[numCols], numCols))
	{
	    printf("Duplicate Columns\n");
	    return -1;
	}

	/* Get length */
	strcpy(tempColName, $3);
	tempColName[strlen(tempColName)-1] = '\0';
	colValues[numCols] = atoi(tempColName);
	/* Check length of maxstrtpe_size */
	if (colValues[numCols] > MAX_STRTYPE_SIZE)
	{
	    printf("MAx strtype size exceeded\n");
	    return -1;
	}
	/* Append query table insert */
	sprintf(message, "@%s c%d",colNames[numCols], colValues[numCols]);
	strcat(tableParameterForQuery,message);
	/* Finally, increment number of columns */	
	numCols++;
	/* Check number of columns */
	if (numCols > MAX_COLUMNS_PER_TABLE)
	{
	    printf("Too many columns in 1 table\n");
	    return -1; 
	}
printf("QUERYNAMEis:%s\n", tableParameterForQuery);
	}

	|

	next_list IMPLICIT_KEY_WITH_COLON INTEGER term
	{
	  printf("next_list IMPLICIT_KEY_WITH_COLON INTEGER \n");
printf("77777777\n");
	/* Get first key */
	strcpy(tempColName, $2);
	tempColName[strlen(tempColName)-2] = '\0';
	/* Check column name length */	
	if (strlen(tempColName) > MAX_COLNAME_LEN)
	{
	    printf("Column name too long\n");
	    return -1;
	}
	/* Store column name */
	strcpy(colNames[numCols], tempColName);
	/* Check column exist */
	if (!checkColumnExist(colNames[numCols], numCols))
	{
	    printf("Duplicate Columns\n");
	    return -1;
	}
	/* Append query table insert */
	sprintf(message, "@%s i",colNames[numCols]);
	strcat(tableParameterForQuery,message);
	/* Finally, increment number of columns */	
	numCols++;
	/* Check number of columns */
	if (numCols > MAX_COLUMNS_PER_TABLE)
	{
	    printf("Too many columns in 1 table\n");
	    return -1; 
	}
printf("QUERYNAMEis:%s\n", tableParameterForQuery);
	}

	|

	IMPLICIT_KEY_WITH_COLON INTEGER term
	{
	  printf("IMPLICIT_KEY_WITH_COLON INTEGER \n");
printf("88888888\n");
	/* Get first key */
	strcpy(tempColName, $1);
	tempColName[strlen(tempColName)-2] = '\0';
	/* Check column name length */	
	if (strlen(tempColName) > MAX_COLNAME_LEN)
	{
	    printf("Column name too long\n");
	    return -1;
	}
	/* Store column name */
	strcpy(colNames[numCols], tempColName);
	/* Check column exist */
	if (!checkColumnExist(colNames[numCols], numCols))
	{
	    printf("Duplicate Columns\n");
	    return -1;
	}
	/* Append query table insert */
	sprintf(message, "@%s i",colNames[numCols]);
	strcat(tableParameterForQuery,message);
	/* Finally, increment number of columns */	
	numCols++;
	/* Check number of columns */
	if (numCols > MAX_COLUMNS_PER_TABLE)
	{
	    printf("Too many columns in 1 table\n");
	    return -1; 
	}
printf("QUERYNAMEis:%s\n", tableParameterForQuery);
	}	
	;

term: COMMA
   {
	printf("next column\n");
   }
   | NEWLINE
   {
	printf("done table\n");
   }
   | ENDOFFILE
   {
	printf("end of file in term for bison\n");
	/* return 0; signal to utils.c no errors */ 
   }
   ;
%%

int checkColumnExist(char* name, int num)
{
    int i = 0;
    for (i = 0; i < numCols; i++)
    {
	if (i != num)
	{
	    if(strcmp(name,colNames[i]) == 0)
		return 0;
	}
    }
    return 1;
}


int checkTableExist(char* name, int num)
{
    int i = 0;
    for (i = 0; i < numTables; i++)
    {
	if (i != num)
	{
	    if(strcmp(name,tableNames[i]) == 0)
		return 0;
	}
    }
    return 1;
}

void clearColumnNames()
{
    int i = 0;
    for (i = 0; i < MAX_COLUMNS_PER_TABLE; i++)
    {
	strcpy(colNames[i], "");
	colValues[i] = 0;
    }
    numCols = 0;
    doneTable = false; 
    return; 
}	

/* Initiliazes configuration if it exist, else, do nothing) */
void initialize_configuration()
{
    if (c != NULL)
    {
	printf("C already initialized\n");
    	return ;
    }
    else
    {
	printf("C going to initialized\n");
	numCols = 0;
        numTables = 0;
	doneTable = false; 
	clearColumnNames();
	int i = 0;
	/* Initialize table names */
	for ( i = 0; i < MAX_TABLES; i++)
	{
	    strcpy(tableNames[i], "");
	}
	strcpy(tableParameterForQuery,"");
	c = (struct configuration *) malloc(sizeof(struct configuration));
	if (c == NULL)
	{
	    printf("Error on malloc `configuration'.\n");
	    exit(-1);
	}
	c->host = "";
	c->port = 0;
	c->tlist = NULL;
	c->data_dir = "";
	c->hostDone = false;
	c->portDone = false;
	c->usernameDone = false;
	c->passwordDone = false;
	c->tableDone = false; 
	c->numTable = 0;
	printf("C is done initializing\n");
	return ;
    }
}

yyerror(char *e)
{
  fprintf(stderr,"%s.\n",e);
}

int print_configuration(struct configuration *c)
{
  struct table *tl;
  printf("Configuration:\n Host: %s, port: %d, data directory: %s\n",
	 c->host, c->port, c->data_dir);
  if (tl){
    tl = c->tlist;
    printf("  Table(s):\n");
    for(;tl; tl = tl->next){
      printf("     %s ",tl->table_name);
    }
    printf("\n");
  } 
}

